﻿using System;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace FscNET.Apm
{
    [Serializable]
    public sealed class Exception<T> : Exception, ISerializable where T : ExceptionArgs
    {
        // Fields
        private const string c_args = "Args";
        private readonly T m_args;

        // Methods
        public Exception()
            : this(null)
        {
        }

        public Exception(string message)
            : this(message, null)
        {
        }

        public Exception(string message, Exception innerException)
            : this(default(T), message, innerException)
        {
        }

        public Exception(T args, string message)
            : this(args, message, null)
        {
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        private Exception(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            m_args = (T)info.GetValue("Args", typeof(T));
        }

        public Exception(T args, string message, Exception innerException)
            : base(message, innerException)
        {
            m_args = args;
        }

        public override bool Equals(object obj)
        {
            Exception<T> exception = obj as Exception<T>;
            if (exception == null)
            {
                return false;
            }
            return (object.Equals(m_args, exception.m_args) && base.Equals(obj));
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Args", m_args);
            base.GetObjectData(info, context);
        }

        public override string ToString()
        {
            return base.ToString();
        }

        // Properties
        public T Args
        {
            get
            {
                return m_args;
            }
        }

        public override string Message
        {
            get
            {
                return (base.Message + ((m_args != null) ? m_args.Message : null));
            }
        }
    }

 

}
